At one time, software applications were monolithic blocks of executable code and data, although some application data such as variable settings could be maintained in separate files. In contrast, contemporary software applications and other executable code (such as operating system components) bind to and make use of self-contained software entities, each of which offers a set of functions that can be used by one or more applications or other executable code. The use of such self-contained software entities enables sharing of the same software entities by different applications, allows the executable files of applications to be kept smaller, enables large development projects to be broken down into smaller projects, and allows updating of the software entities without having to update the applications that use them.
An assembly is one such self-contained software entity. In particular, an assembly is a code library for use in deployment, versioning and security in the MICROSOFT® .NET framework. Assemblies are generated by compiling source code (e.g., C#, C++, or Visual Basic source code) using an appropriately configured compiler (e.g., a MICROSOFT® .NET compiler). An assembly includes metadata and intermediate language instructions. The metadata describes code elements defined in the source code, such as types, members (e.g., methods, fields, properties, events) and attributes. The intermediate language instructions are operation codes that perform operations when an assembly is executed. A just-in-time compiler that translates assemblies into machine-specific executable code facilitates the coordination of operation codes and portions of metadata at the time of execution.
Static code analysis tools exist that analyze software entities, such as assemblies, without actually having to execute the software entities or the applications that make use of them. Static code analysis tools may be used by developers to detect defects in software entities and/or to ensure compliance by the software entities with program specifications or development guidelines. Depending upon the implementation, static code analysis tools may be embodied as stand-alone applications or may comprise a part of an integrated development environment (IDE).
A static code analysis tool may be invoked to analyze an assembly that is part of a collection of assemblies used to implement an application or other executable code. The assembly to be analyzed may be termed the target assembly. To analyze a code element in the target assembly, the static code analysis tool may need to obtain a suitable definition of the code element from the target assembly metadata. However, it may be that the code element included in the target assembly cannot be suitably defined without reference to a second code element included in another assembly in the collection of assemblies. For example, it may be that a method of a particular type that is included in the target assembly cannot be suitably defined without reference to a definition of a type that is included in another assembly in the collection of assemblies. In this case, the first code element can be said to be dependent on the second code element. The second code element, in turn, may be dependent upon another code element located in another assembly in the collection and so on. Thus, to obtain a suitable definition of the first code element, the static code analysis tool may be required to read the target assembly as well as other assemblies that include code elements upon which the first code element depends either directly or indirectly. These other assemblies may be referred to as reference assemblies.
One conventional approach to ensuring that any such dependencies can be resolved by the static code analysis tool requires loading every assembly in the collection of assemblies into system memory prior to analysis of the target assembly. This may be referred to as loading the full closure of assemblies. Often times, this approach results in loading significantly more information that is actually needed and can introduce performance problems where system memory is limited. This approach can also introduce reliability problems because it requires that all the reference assemblies be accessible to the computer executing the static code analysis tool, which is not always the case.
Another conventional approach involves on-demand reading of assemblies to resolve dependencies. In accordance with this approach, when the static code analysis tool is reading a first code element in a first assembly and determines that the first code element refers to a second code element included in another assembly, the static code analysis tool will attempt to read the second code element from the other assembly at that time to resolve the dependency. If the second code element further depends on a third code element, then the static code analysis tool will also attempt to read the third code element to resolve the dependency at that time. This process continues until all direct and indirect dependencies of the first code element are resolved. For example, assume that a method A calls a method B, method B calls a method C, and method C calls a method D. In an implementation in which the load-on-demand approach is used to obtain a suitable definition of method A, the static code analysis tool will load all four methods and any types that those methods require. While this approach typically reduces the amount of information read out of each assembly as compared to the approach of loading the full closure of assemblies, this approach may still result in the loading of more information than is actually needed. For example, with continued reference to the previous example involving methods A, B, C and D, it may be that in order to obtain a suitable definition of method A, the static code analysis tool only needs to load a signature and method body of method A and just the signature of method B. Method C and D may not need to be loaded at all. In addition, the types that method B refers to may need only be named placeholders and thus need not be loaded from an actual assembly.
What is needed, then, is an improved system and method for loading code elements included in a plurality of software entities that include a target software entity and one or more reference software entities to facilitate analysis of the target software entity by a code analysis tool, such as a static code analysis tool. The improved system and method should address one or more of the shortcomings associated with conventional approaches to loading code elements as described above.